﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Net.Http.Headers;
using System.Runtime.Serialization;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Auth;
using Microsoft.WindowsAzure.Storage.Blob;

namespace BESClient
{
    public partial class Noinputoutput : System.Web.UI.Page
    {
        string[] webServiceParamNameArray;
        string[] webServiceParamValuesArray;
        protected void Page_Load(object sender, EventArgs e)
        {
        }
        protected void btnSubmit_Click(object sender, EventArgs e)
        {
            //Get web service parameters
            string webServiceParamNames = txtParams.Text;
            string webServiceParamValues = txtParamValues.Text;

            //Check for web service parameters if entered            
            if (webServiceParamNames != "" || webServiceParamValues != "")
            {
                //Both are required if one is entered
                if (webServiceParamNames.Length == 0 || webServiceParamValues.Length == 0)
                {
                    divResult.InnerHtml = "Error: Both web service parameter names and values must be entered.";
                }
                else
                {
                    //create arrays of name/values and make sure the counts match
                    webServiceParamNameArray = webServiceParamNames.Split(',');
                    webServiceParamValuesArray = webServiceParamValues.Split(',');

                    if (webServiceParamNameArray.Length != webServiceParamValuesArray.Length)
                    {
                        divResult.InnerHtml = "Error: Parameter names and values count must match.";
                    }
                    else
                    {
                        InvokeBatchExecutionService().Wait();
                    }
                }
            }
            else//now web service parameters
            {
                InvokeBatchExecutionService().Wait();
            }

        }
        private async Task WriteFailedResponse(HttpResponseMessage response)
        {
            divResult.InnerHtml += string.Format("The request failed with status code: {0}<br/>", response.StatusCode);

            // Print the headers - they include the requert ID and the timestamp, which are useful for debugging the failure
            divResult.InnerHtml += response.Headers.ToString();

            string responseContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
            divResult.InnerHtml += responseContent;
        }
        private async Task InvokeBatchExecutionService()
        {
            Util util = new Util();
            string BaseUrl = util.setPostURLString(txtUrl.Text);//remove ?api if passed in 
            string apiKey = txtKey.Text; // Replace this with the API key for the web service

            // set a time out for polling status
            const int TimeOutInMilliseconds = 120 * 1000; // Set a timeout of 2 minutes

            Dictionary<string, string> webparams = new Dictionary<string, string>() { };
            //Add web service paramter to dictionary for input (if available)
            if (webServiceParamNameArray != null && webServiceParamValuesArray != null)
            {
                if (webServiceParamNameArray.Length > 0 && webServiceParamValuesArray.Length > 0)
                {
                    for (int i = 0; i < webServiceParamNameArray.Length; i++)
                    {
                        webparams.Add(webServiceParamNameArray[i], webServiceParamValuesArray[i]);
                    }
                }
            }
            using (HttpClient client = new HttpClient())
            {
                var request = new BatchScoreRequest()
                {
                    GlobalParameters = webparams
                };

                client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", apiKey);

                var response = await client.PostAsJsonAsync(BaseUrl, request).ConfigureAwait(false);
                if (!response.IsSuccessStatusCode)
                {
                    await WriteFailedResponse(response).ConfigureAwait(false);
                    return;
                }

                string jobId = await response.Content.ReadAsAsync<string>().ConfigureAwait(false);
                divResult.InnerHtml = string.Format("Job ID: {0}<br/>", jobId);

                string jobLocation = BaseUrl + "/" + jobId + "";
                Stopwatch watch = Stopwatch.StartNew();
                bool done = false;
                while (!done)
                {
                    response = await client.GetAsync(jobLocation).ConfigureAwait(false);
                    if (!response.IsSuccessStatusCode)
                    {
                        await WriteFailedResponse(response).ConfigureAwait(false);
                        return;
                    }

                    BatchScoreStatus status = await response.Content.ReadAsAsync<BatchScoreStatus>().ConfigureAwait(false);
                    if (watch.ElapsedMilliseconds > TimeOutInMilliseconds)
                    {
                        done = true;
                        divResult.InnerHtml += string.Format("Timed out. Deleting job {0} ...<br/>", jobId);
                        await client.DeleteAsync(jobLocation).ConfigureAwait(false);
                    }
                    switch (status.StatusCode)
                    {
                        case BatchScoreStatusCode.NotStarted:
                            //divResult.InnerHtml +=string.Format("Job {0} not yet started...", jobId);
                            break;
                        case BatchScoreStatusCode.Running:
                            //divResult.InnerHtml +=string.Format("Job {0} running...", jobId);
                            break;
                        case BatchScoreStatusCode.Failed:
                            divResult.InnerHtml += string.Format("Job {0} failed!<br/>", jobId);
                            divResult.InnerHtml += string.Format("Error details: {0}<br/>", status.Details);
                            done = true;
                            break;
                        case BatchScoreStatusCode.Cancelled:
                            divResult.InnerHtml += string.Format("Job {0} cancelled!<br/>", jobId);
                            done = true;
                            break;
                        case BatchScoreStatusCode.Finished:
                            done = true;
                            divResult.InnerHtml += string.Format("Job {0} finished! <br/> Check Writer output location for results.<br/>", jobId);

                            divResult.InnerHtml += "Response: ";
                            divResult.InnerHtml += await response.Content.ReadAsStringAsync().ConfigureAwait(false);
                            break;
                    }

                    if (!done)
                    {
                        Thread.Sleep(1000); // Wait one second
                    }
                }
            }
        }
    }

}